#ifdef _CH_
#pragma package <opencv>
#endif


#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "sobel.h"

#include <iostream> 
using namespace std;

int thresh = 50;
IplImage *img = 0;
IplImage *imgf = 0;
IplImage *imgtmp = 0;
IplImage *imgx = 0;
IplImage *imgy = 0;
IplImage *imgxy = 0;
IplImage *imglap = 0;
IplImage *imglapcv = 0;
const char *wndname_orig = "Original";
const char *wndnamex = "Derivada 2a em x";
const char *wndnamey = "Derivada 2a em y";
const char *wndnamelap = "Laplaciano";
const char *wndnamelapcv = "Laplaciano alternativo";

 
int main (int argc, char **argv)
{
  int i, c;


  if (argc < 2) {
    printf ("Usage: %s <filename>/n", argv[0]);
    exit(1);
  }

  //
  // Lê arquivo de entrada. Imagens são convertidas para Grace Kelly.
  img = cvLoadImage (argv[1], CV_LOAD_IMAGE_GRAYSCALE);

  if (!img) {
    printf ("Couldn't load %s\n", argv[1]);
    exit(2);
  }
  

  // Cria imagens do mesmo tamanho q a entrada, double, um canal.
  CvSize img_size = cvGetSize(img);

  imgf = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  imgtmp = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  imgx = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  imgy = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  imglap = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  imglapcv = cvCreateImage(img_size, IPL_DEPTH_32F, 1);
  // Pra trabalhar com char ao invés de float...
  //imgx = cvCreateImage(img_size, IPL_DEPTH_8U, 1);
  //imgy = cvCreateImage(img_size, IPL_DEPTH_8U, 1);
  //imglap = cvCreateImage(img_size, IPL_DEPTH_8U, 1);

  // Copia (converte formato e arruma escala...)
  //cvConvertScale(img, imgf, 1/255.0, -128);
  cvConvertScale(img, imgf, 1/255.0, 0);


  // Chama o 'seu' Sobel pra trabalhar.
  int ordem=3; // tamanho da janela do Sobel... default é 3.

  cvSobel (imgf, imgx, 2, 0, ordem);
  cvSobel (imgf, imgy, 0, 2, ordem);


  // Calcula extremos
  double minx, miny;
  double maxx, maxy;
  cvMinMaxLoc( imgx, &minx, &maxx);
  cvMinMaxLoc( imgy, &miny, &maxy);

  cout << minx << ' '
       << miny << ' '
       << maxx << ' '
       << maxy << endl;
  

  // Arruma as escalas, pq os valores devem ser entre 0.0 e 1.0 na
  // hora de mostrar na tela. Pra isso, calculamos uma mesma escala a
  // ser aplicada às duas imagens.
  // Lembrete: estudar a possibilidade de usar cvNormalize...

   
  //get_properties(imgx,wndnamex);
  //get_properties(imgy,wndnamey);

  //modulus(imgx,imgy,imglap);

  


  // Calcula o laplaciano de duas imagens, somando as derivadas 2a em
  // x e em y
  cvAdd(imgx, imgy, imglap);

  // Ou a versão dentro do OpenCV (já aplica um filtro só)
  cvLaplace(imgf, imglapcv, ordem);
  
  // Parte GUI
  cvNamedWindow (wndname_orig, 2);
  cvNamedWindow (wndnamex, 2);
  cvNamedWindow (wndnamey, 2);
  cvNamedWindow (wndnamelap, 2);
  cvNamedWindow (wndnamelapcv, 2);

  cvMoveWindow (wndname_orig, 50 , 10);
  cvMoveWindow (wndnamex, 400, 10);
  cvMoveWindow (wndnamey, 50, 310);
  cvMoveWindow (wndnamelap, 400, 310);
  cvMoveWindow (wndnamelapcv, 700, 310);
  


  double sc;
  sc=1.0;
  cvConvertScale(imgf, imgtmp, 1.0, 0);
  cvShowImage (wndname_orig, imgtmp);
  
  sc=1/4.0;
  cvConvertScale(imgx, imgtmp, sc, 0.5);
  cvShowImage (wndnamex, imgtmp);
  cvConvertScale(imgy, imgtmp, sc, 0.5);
  cvShowImage (wndnamey, imgtmp);

  sc=1.0/2.0;
  cvConvertScale(imglap, imgtmp, sc, 0);
  cvShowImage (wndnamelap, imgtmp);
  cvConvertScale(imglap, imgtmp, sc, 0);
  cvShowImage (wndnamelapcv, imgtmp);
  
  c = cvWaitKey(0);
  
  cvReleaseImage (&img);
  cvReleaseImage (&imgx);
  cvReleaseImage (&imgy);
  cvReleaseImage (&imglap);
  
  cvDestroyAllWindows ();
  return 0;
  
}
